﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using BasePlatformNet;

namespace L9SubSet {
    public partial class Form_ArtNetTool : Form {
        private BaseCoreNet core;
        private CaptureSendState captureState = CaptureSendState.Run;
        private string lastIdentifyUID = "";
        public Form_ArtNetTool(BaseCoreNet netCore) {
            InitializeComponent();

            this.core = netCore;
            captureState = core.GetCaptureSendState();
            btnStop.Visible = false;
        }

        private void BtnFindDev_Click(object sender, EventArgs e) {
            var process = new Action(() => {
                core.QueryArtSubControl();
            });
            runSingleTask(process, () => {
                var list = core.GetUnvList();
                if (list != null && list.Count != 0) {
                    ArtDeviceComboBox.Items.Clear();
                    ArtDeviceComboBox.Items.Add("All");
                    foreach (var unv in list) {
                        ArtDeviceComboBox.Items.Add(unv);
                    }
                    ArtDeviceComboBox.SelectedIndex = 0;
                    ArtDeviceComboBox.Enabled = true;
                    setQueryEnable(true);
                } else {
                    ArtDeviceComboBox.Enabled = false;
                    setQueryEnable(false);
                }
            });
        }

        private void btnReadDevChain_Click(object sender, EventArgs e) {
            var process = new Action(() => {
                core.ReadArtDeviceChainDetail();
            });
            runSingleTask(process, () => {
                var list = core.ArtDevDetailList;
                if (list == null) {
                    return;
                }
                tbDevInfo.Text = list.ToString();
            });
        }

        private void BtnUIDAll_Click(object sender, EventArgs e)
        {
            var unv = getSelectUnv();
            var process = new Action(() => {
                if (unv == -1) {
                    core.QueryUIDListTotal();
                } else {
                    core.QueryUIDList(unv);
                }
            });
            runSingleTask(process, () => {
                showUIDList();
            });
        }

        private void BtnGetUIDRe_Click(object sender, EventArgs e)
        {
            var unv = getSelectUnv();
            var process = new Action(() => {
                if (unv == -1) {
                    core.RequeryUIDListTotal();
                } else {
                    core.RequeryUIDList(unv);
                }
            });
            runSingleTask(process, () => {
                showUIDList();
            });
        }

        private void btnIdentify_Click(object sender, EventArgs e)
        {
            var uid = getSelectUID();
            var unv = getRealUnv(uid);
            var process = new Action(() => {
                if (!string.IsNullOrEmpty(lastIdentifyUID)) {
                    core.IdentifyArtDevice(lastIdentifyUID, getRealUnv(lastIdentifyUID), false);
                }
                core.IdentifyArtDevice(uid, unv, true);
                lastIdentifyUID = uid;
            });
            runSingleTask(process, () => {
            });
        }

        private void btnStopIdentify_Click(object sender, EventArgs e)
        {
            var uid = getSelectUID();
            var unv = getRealUnv(uid);
            var process = new Action(() => {
                core.IdentifyArtDevice(uid, unv, false);
                lastIdentifyUID = "";
            });
            runSingleTask(process, () => {
            });
        }

        private void btnGetVer_Click(object sender, EventArgs e) {
            var verLabel = "";
            var uid = getSelectUID();
            var unv = getRealUnv(uid);
            var process = new Action(() => {
                verLabel = core.ReadSoftwareVersionLabel(uid, unv);
            });
            runSingleTask(process, () => {
                var item = new Item("Software Version Label", verLabel);
                showRDMPara(new List<Item> { item });
            });
        }

        private void btnGetDMXAddr_Click(object sender, EventArgs e) {
            var addr = 0;
            var uid = getSelectUID();
            var unv = getRealUnv(uid);
            var process = new Action(() => {
                addr = core.ReadArtDmxAddr(uid, unv);
            });
            runSingleTask(process, () => {
                var item = new Item("DMX512 Start Addr", addr);
                showRDMPara(new List<Item> { item });
            });
        }

        private void btnSensor_Click(object sender, EventArgs e)
        {
            var uid = getSelectUID();
            var retList = new List<ArtSensorInfo>();
            var process = new Action(() => {
                var unv = getRealUnv(uid);
                var info = getDevInfo(uid);
                if (info == null) {
                    return;
                }
                var list = info.SensorList;
                if (list == null || list.Count == 0) {
                    return;
                }
                for (var i = 0; i < list.Count; i++) {
                    var sensorInfo = list[i];
                    var def = sensorInfo.Definition;
                    var id = def.ID;
                    var val = core.ReadSensorValue(uid, unv, id);
                    val.Prefix = def.Prefix;
                    sensorInfo.Value = val;
                }
                retList.AddRange(list);
            });
            runSingleTask(process, () => {
                var list = new List<Item>();
                for (var i = 0; i < retList.Count; i++) {
                    var sensorInfo = retList[i];
                    var item = new Item(sensorInfo.Definition.Description, sensorInfo.Value.RealCurrVal);
                    list.Add(item);
                }
                showRDMPara(list);
            });
        }

        private void btnSetDMXAddr_Click(object sender, EventArgs e) {
            var unv = getSelectUnv();
            var uid = getSelectUID();
            if (unv == -1) {
                unv = getRealUnv(uid);
            }
            var addr = getDMXAddr();
            var process = new Action(() => {
                core.SetArtDmxAddr(uid, unv, addr);
            });
            runSingleTask(process, () => { });
        }

        private void btnStop_Click(object sender, EventArgs e) {
            
        }

        private void setCaptureState(bool state) {
            if (state) {
                btnStop.Text = "停止截屏下发";
            } else {
                btnStop.Text = "恢复截屏下发";
            }
        }

        private void ArtDeviceComboBox_SelectedIndexChanged(object sender, EventArgs e) {
            showUIDList();
        }

        private void RDMDiscoveryView_CellMouseUp(object sender, DataGridViewCellMouseEventArgs e) {
            var uid = getSelectUID();
            showDevDetails(uid);
        }

        private void setLampOperEnable(bool enable) {
            btnSensor.Enabled = enable;
            btnGetVer.Enabled = enable;
            btnGetDMXAddr.Enabled = enable;
            btnSetDMXAddr.Enabled = enable;
            tbDMXAddr.Enabled = enable;
        }

        private void setQueryEnable(bool enable) {
            BtnUIDAll.Enabled = enable;
            BtnGetUIDRe.Enabled = enable;
        }

        private void runSingleTask(Action task, Action callback) {
            var pending = true;
            var thread = new Thread(() => { 
                task();
                pending = false;
            });
            thread.Start();
            while (pending) {
                Thread.Sleep(1);
            }
            BeginInvoke(callback);
        }

        private int getSelectUnv() {
            var unv = -1;
            if (ArtDeviceComboBox.Items.Count == 0 || ArtDeviceComboBox.SelectedIndex == 0) {
                return unv;
            }
            unv = int.Parse(ArtDeviceComboBox.Text);
            return unv;
        }

        private string getSelectUID() {
            var uid = "";
            if (RDMDiscoveryView.Rows.Count == 0) {
                return uid;
            }
            uid = RDMDiscoveryView.SelectedRows[0].Cells[0].Value.ToString();
            return uid;
        }

        private int getDMXAddr() {
            var addr = 0;
            if (!int.TryParse(tbDMXAddr.Text, out addr)) {
                return 0;
            }
            return addr;
        }

        private int getRealUnv(string uid) {
            var uidList = core.GetUIDList();
            var unv = -1;
            foreach (var item in uidList) {
                var list = item.Value;
                if (list.Contains(uid)) {
                    unv = item.Key;
                    break;
                }
            }
            return unv;
        }

        private void showUIDList() {
            var unv = getSelectUnv();
            var uidList = core.GetUIDList();
            RDMDiscoveryView.Rows.Clear();
            setLampOperEnable(false);
            if(uidList == null){
                return;
            }
            if (unv == -1) {
                foreach (var list in uidList.Values) {
                    if (list == null || list.Count == 0) {
                        continue;
                    }
                    foreach (var uid in list) {
                        showDevInfo(uid);
                    }
                }
            } else {
                if (uidList.ContainsKey(unv)) {
                    var list = uidList[unv];
                    if (list == null || list.Count == 0) {
                        return;
                    }
                    foreach (var uid in list) {
                        showDevInfo(uid);
                    }
                }
            }
            setLampOperEnable(true);
        }

        private void showDevInfo(string uid) {
            if (uid != null) {
                var info = core.GetArtDevInfo(uid);
                var rowindex = RDMDiscoveryView.Rows.Add();
                RDMDiscoveryView.Rows[rowindex].Cells[0].Value = uid;
                if (info != null) {
                    RDMDiscoveryView.Rows[rowindex].Cells[1].Value = uid.Substring(0, 4);
                    RDMDiscoveryView.Rows[rowindex].Cells[2].Value = info.ModelID;
                    RDMDiscoveryView.Rows[rowindex].Cells[3].Value = info.Personality;
                    RDMDiscoveryView.Rows[rowindex].Cells[4].Value = info.Footprint;
                    RDMDiscoveryView.Rows[rowindex].Cells[5].Value = info.DMXAddr;
                }
            }
        }

        private void showDevDetails(string uid) {
            var unv = getRealUnv(uid);
            var info = getDevInfo(uid);
            if (info == null) {
                return;
            }
            tbDevInfo.Text = info.ToString();
        }

        private void showRDMPara(List<Item> list) {
            if (list == null || list.Count == 0) {
                return;
            }
            var text = "";
            foreach (var item in list) {
                text += string.Format("{0:32}:{1}\r\n", item.key, item.value.ToString());
            }
            tbPara.Text = text;
        }

        private ArtDeviceInfo getDevInfo(string uid) {
            var info = core.GetArtDevInfo(uid);
            if (info == null) {
                var process = new Action(() => {
                    var unv = getRealUnv(uid);
                    info = core.ReadArtDevDetail(uid, unv);
                });
                runSingleTask(process, () => {

                });
            }
            return info;
        }

        private class Item {
            internal string key;
            internal object value;

            internal Item(string key, object value) {
                this.key = key;
                this.value = value;
            }
        }
    }
}
